#include <iostream>
#include <stdio.h>
#include <stdlib.h>

#include "Bank.h"
#include "BankSupport.h"
#include "ndds/ndds_requestreply_cpp.h"

using namespace DDS;
DomainParticipant *participant = NULL;

/* Delete all entities */
static int client_shutdown(
    DomainParticipant *participant)
{
    ReturnCode_t retcode;
    int status = 0;

    if (participant != NULL) {
        retcode = participant->delete_contained_entities();
        if (retcode != RETCODE_OK) {
            printf("delete_contained_entities error %d\n", retcode);
            status = -1;
        }

        retcode = TheParticipantFactory->delete_participant(participant);
        if (retcode != RETCODE_OK) {
            printf("delete_participant error %d\n", retcode);
            status = -1;
        }
        participant = NULL;
    }

    /* RTI Connext provides the finalize_instance() method on
       domain participant factory for people who want to release memory used
       by the participant factory. Uncomment the following block of code for
       clean destruction of the singleton. */
/*
    retcode = DomainParticipantFactory::finalize_instance();
    if (retcode != RETCODE_OK) {
        printf("finalize_instance error %d\n", retcode);
        status = -1;
    }
*/
    return status;
}

extern "C" int client_main(int domainId, int sample_count)
{
    //Subscriber *subscriber = NULL;
    //Topic *topic = NULL;
    //Bank_AddressListener *reader_listener = NULL; 
    //DataReader *reader = NULL;
    //ReturnCode_t retcode;
    //const char *type_name = NULL;
    int count = 0;
    Duration_t receive_period = {4,0};
    int status = 0;

    /* To customize the participant QoS, use 
       the configuration file USER_QOS_PROFILES.xml */
    participant = TheParticipantFactory->create_participant(
        domainId, PARTICIPANT_QOS_DEFAULT, 
        NULL /* listener */, STATUS_MASK_NONE);
    if (participant == NULL) {
        printf("create_participant error\n");
        client_shutdown(participant);
        return -1;
    }

	connext::Requester<Bank::Account_balance_request, 
		               Bank::Account_balance_reply> requester(participant, "BankAccount");
	
	Bank::Account_balance_request request;

	/* Main loop */
    for (count=0; (sample_count == 0) || (count < sample_count);) 
    {
      request.request_id = count;
      requester.send_request(request);
      connext::Sample<Bank::Account_balance_reply> reply_sample;
      requester.receive_reply(reply_sample, receive_period);

      if(reply_sample.info().valid_data)
      {
        if(reply_sample.data().result._d == 0)
        {
          std::cout << "received reply = "  
                    << reply_sample.data().result._u.balance._return
                    << std::endl;
          ++count;
        }
      }
        //NDDSUtility::sleep(receive_period);
    }

    /* Delete all entities */
    status = client_shutdown(participant);
    return status;
}

int main(int argc, char *argv[])
{
    int domainId = 65;
    int sample_count = 0; /* infinite loop */

    if (argc >= 2) {
        domainId = atoi(argv[1]);
    }
    if (argc >= 3) {
        sample_count = atoi(argv[2]);
    }

    /* Uncomment this to turn on additional logging
    NDDSConfigLogger::get_instance()->
        set_verbosity_by_category(NDDS_CONFIG_LOG_CATEGORY_API, 
                                  NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL);
    */
    try {                              
      return client_main(domainId, sample_count);
    }
    catch(std::exception & ex)
    {
      std::cout << "Exception: " << ex.what() << std::endl;
      return client_shutdown(participant);
    }
}

